package com.zenithmind.news.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zenithmind.news.mapper.NewsMapper;
import com.zenithmind.news.mapper.NewsMapper.NewsStatistics;
import com.zenithmind.news.mapper.NewsMapper.TagStatistics;
import com.zenithmind.news.mapper.NewsMapper.NewsTrend;
import com.zenithmind.news.mapper.NewsStatisticsMapper;
import com.zenithmind.news.pojo.entity.News;
import com.zenithmind.news.service.NewsCacheService;
import com.zenithmind.news.service.NewsStatisticsService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.List;

/**
 * 新闻统计服务实现类 - 遵循单一职责原则
 * 专门负责新闻的统计分析功能
 * 
 * @author ZenithMind Team
 * @since 2025-01-09
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class NewsStatisticsServiceImpl extends ServiceImpl<NewsMapper, News> implements NewsStatisticsService {

    private final NewsMapper newsMapper;
    private final NewsStatisticsMapper newsStatisticsMapper;
    private final NewsCacheService newsCacheService;

    @Override
    public Boolean updateNewsStatistics(String newsId, Long viewCount, Long likeCount, 
                                       Long favoriteCount, Long shareCount, Long commentCount) {
        try {
            int updated = newsMapper.updateStatistics(newsId, viewCount, likeCount, 
                                                     favoriteCount, shareCount, commentCount);
            if (updated > 0) {
                // 清除相关缓存
                newsCacheService.evictNewsCache(newsId);
                log.debug("更新新闻统计成功：{}", newsId);
                return true;
            }
            return false;
        } catch (Exception e) {
            log.error("更新新闻统计失败：{}", newsId, e);
            return false;
        }
    }

    @Override
    public Double calculateHotScore(String newsId) {
        try {
            News news = getById(newsId);
            if (news == null) {
                return 0.0;
            }

            // 获取统计数据
            double baseScore = calculateBaseScore(news);

            // 时间衰减因子
            double timeDecay = calculateTimeDecay(news);

            // 最终热度评分
            double hotScore = baseScore * timeDecay;

            // 更新数据库中的热度评分
            newsStatisticsMapper.updateHotScore(newsId, hotScore);

            log.debug("计算新闻热度：{} -> {}", newsId, hotScore);
            return Math.round(hotScore * 100.0) / 100.0;
        } catch (Exception e) {
            log.error("计算新闻热度失败：{}", newsId, e);
            return 0.0;
        }
    }

    @Override
    public Boolean batchUpdateStatus(List<String> newsIds, Integer status) {
        try {
            int updated = newsMapper.batchUpdateStatus(newsIds, status);
            if (updated > 0) {
                // 清除相关缓存
                newsIds.forEach(newsCacheService::evictNewsCache);
                log.info("批量更新新闻状态成功：{} 条", updated);
                return true;
            }
            return false;
        } catch (Exception e) {
            log.error("批量更新新闻状态失败", e);
            return false;
        }
    }

    @Override
    public NewsStatistics getNewsStatistics(String categoryId, LocalDateTime startTime, LocalDateTime endTime) {
        try {
            return newsMapper.selectNewsStatistics(categoryId, startTime, endTime);
        } catch (Exception e) {
            log.error("获取新闻统计失败：分类={}, 开始时间={}, 结束时间={}", categoryId, startTime, endTime, e);
            return null;
        }
    }

    @Override
    public List<TagStatistics> getHotTags(Integer limit) {
        try {
            return newsMapper.selectHotTags(limit);
        } catch (Exception e) {
            log.error("获取热门标签失败：limit={}", limit, e);
            return List.of();
        }
    }

    @Override
    public List<NewsTrend> getNewsTrend(Integer days) {
        try {
            return newsMapper.selectNewsTrend(days);
        } catch (Exception e) {
            log.error("获取新闻趋势失败：days={}", days, e);
            return List.of();
        }
    }

    /**
     * 计算基础评分
     * 从NewsStatistics表获取统计数据并计算评分
     */
    private double calculateBaseScore(News news) {
        try {
            // 从NewsStatistics表获取统计数据
            com.zenithmind.news.pojo.entity.NewsStatistics statistics =
                newsStatisticsMapper.selectByNewsId(news.getId());

            if (statistics == null) {
                // 如果没有统计数据，初始化一条记录
                newsStatisticsMapper.initNewsStatistics(news.getId());
                return 0.0;
            }

            // 计算基础评分：根据各项指标加权计算
            double viewScore = (statistics.getViewCount() != null ? statistics.getViewCount() : 0L) * 0.1;
            double likeScore = (statistics.getLikeCount() != null ? statistics.getLikeCount() : 0L) * 2.0;
            double favoriteScore = (statistics.getFavoriteCount() != null ? statistics.getFavoriteCount() : 0L) * 3.0;
            double shareScore = (statistics.getShareCount() != null ? statistics.getShareCount() : 0L) * 4.0;
            double commentScore = (statistics.getCommentCount() != null ? statistics.getCommentCount() : 0L) * 1.5;
            double qualityScore = (statistics.getQualityScore() != null ? statistics.getQualityScore() : 0.8) * 10.0;

            // 综合评分
            double totalScore = viewScore + likeScore + favoriteScore + shareScore + commentScore + qualityScore;

            // 应用对数函数平滑评分，避免评分过高
            return Math.log(1 + totalScore);

        } catch (Exception e) {
            log.error("计算基础评分失败：{}", news.getId(), e);
            return 0.0;
        }
    }

    /**
     * 计算时间衰减因子
     */
    private double calculateTimeDecay(News news) {
        if (news.getPublishTime() == null) {
            return 1.0;
        }
        
        long hours = ChronoUnit.HOURS.between(news.getPublishTime(), LocalDateTime.now());
        // 24小时衰减模型：e^(-hours/24)
        return Math.exp(-hours / 24.0);
    }
}
